﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading;

using NoDeadLockReadWriteLocker;

namespace PerformanceGraph
{
	public partial class Races : Form
	{
		private const int MaxProgress = 10000;
		private const int MaxThreads  = 6;
		private const int MaxHorses   = 6;

		private ReaderWriterLockSlim _NitroLock       = new ReaderWriterLockSlim(LockRecursionPolicy.SupportsRecursion);
		private ReaderWriterLockSlim _LightningLock   = new ReaderWriterLockSlim(LockRecursionPolicy.SupportsRecursion);
		private ReaderWriterLock     _EeyoreLock      = new ReaderWriterLock();
		private ReaderWriterLock     _PinTheTailLock  = new ReaderWriterLock();
		private ReadWriteLocker _LittleBlueEngineLock;
		private ReadWriteLocker _TheodoreTugboatLock;

		private Thread[] _NitroThread = new Thread[MaxThreads];
		private Thread[] _LightningThread = new Thread[MaxThreads];
		private Thread[] _EeyoreThread = new Thread[MaxThreads];
		private Thread[] _PinTheTailThread = new Thread[MaxThreads];
		private Thread[] _LittleBlueEngineThread = new Thread[MaxThreads];
		private Thread[] _TheodoreTugboatThread = new Thread[MaxThreads];

		private int _NitroProgress = 0;
		private int _LightningProgress = 0;
		private int _EeyoreProgress = 0;
		private int _PinTheTailProgress = 0;
		private int _LittleBlueEngineProgress = 0;
		private int _TheodoreTugboatProgress = 0;

		private int _NitroFinished = 0;
		private int _LightningFinished = 0;
		private int _EeyoreFinished = 0;
		private int _PinTheTailFinished = 0;
		private int _LittleBlueEngineFinished = 0;
		private int _TheodoreTugboatFinished = 0;

		private DateTime _NitroStartTime = DateTime.Now;
		private DateTime _LightningStartTime = DateTime.Now;
		private DateTime _EeyoreStartTime = DateTime.Now;
		private DateTime _PinTheTailStartTime = DateTime.Now;
		private DateTime _LittleBlueEngineStartTime = DateTime.Now;
		private DateTime _TheodoreTugboatStartTime = DateTime.Now;

		// This allows the jockey threads to mount their horses
		//   before anyone is allowed to take off for the finish line.
		private int _JockeysAreGettingReady;

		// When this matches the number of threads, the horses take off.
		private int _HorcesAreOff;
		private int _FirstTrott;

		private bool _TestingSpeed;

		protected enum HorseType
		{
			Nitro            = 0,
			Lightning        = 1,
			Eeyore           = 2,
			PinTheTail       = 3,
			LittleBlueEngine = 4,
			TheodoreTugboat  = 5
		} // End HorseType enum

		private delegate void PressGallopButtonMethod(HorseType type, bool pressed);
		private delegate int  GetMethod(HorseType type);
		private delegate void SetMethod(HorseType type, int value);

		public Races()
		{
			InitializeComponent();

			if (DialogResult.Yes ==
			    MessageBox.Show(this, "Do you want to include checking for deadlocks?",
			    "Deadlocks are impossible here, but this allows testing deadlock prevention performance.",
			    MessageBoxButtons.YesNo, MessageBoxIcon.Question))
			{
				_LittleBlueEngineLock = new ReadWriteLocker(ReadWriteLocker.Behavior.NoDeadLocks);
				_TheodoreTugboatLock = new ReadWriteLocker(ReadWriteLocker.Behavior.NoDeadLocks);
			} else {
				_LittleBlueEngineLock = new ReadWriteLocker(ReadWriteLocker.Behavior.AllowDeadLocks);
        _TheodoreTugboatLock = new ReadWriteLocker(ReadWriteLocker.Behavior.AllowDeadLocks);
			} // End if
		} // End Constructor

		private void InitializeThreads()
		{
			_NitroFinished = 1;
			_LightningFinished = 1;
			_EeyoreFinished = 1;
			_PinTheTailFinished = 1;
			_LittleBlueEngineFinished = 1;
			_TheodoreTugboatFinished = 1;

			_NitroProgress            = MaxProgress;
			_LightningProgress        = MaxProgress;
			_EeyoreProgress           = MaxProgress;
			_PinTheTailProgress       = MaxProgress;
			_LittleBlueEngineProgress = MaxProgress;
			_TheodoreTugboatProgress  = MaxProgress;

			for (int i = 0; i < MaxThreads; ++i)
			{
				if (_NitroThread[i] != null)            {_NitroThread[i].Join();}
				if (_LightningThread[i] != null)	       {_LightningThread[i].Join();}
				if (_EeyoreThread[i] != null)           {_EeyoreThread[i].Join();}
				if (_PinTheTailThread[i] != null)       {_PinTheTailThread[i].Join();}
				if (_LittleBlueEngineThread[i] != null) {_LittleBlueEngineThread[i].Join();}
				if (_TheodoreTugboatThread[i] != null)  {_TheodoreTugboatThread[i].Join();}
			} // End for

			_NitroProgress = 0;
			_LightningProgress = 0;
			_EeyoreProgress = 0;
			_PinTheTailProgress = 0;
			_LittleBlueEngineProgress = 0;
			_TheodoreTugboatProgress = 0;

			for (int i = 0; i < MaxThreads; ++i)
			{
				_NitroThread[i]            = new Thread(new ThreadStart(NitroHorse));
				_LightningThread[i]        = new Thread(new ThreadStart(LightningHorse));
				_EeyoreThread[i]           = new Thread(new ThreadStart(EeyoreHorse));
				_PinTheTailThread[i]       = new Thread(new ThreadStart(PinTheTailHorse));
				_LittleBlueEngineThread[i] = new Thread(new ThreadStart(LittleBlueEngineHorse));
				_TheodoreTugboatThread[i]  = new Thread(new ThreadStart(TheodoreTugboatHorse));
			} // End for

			Thread.MemoryBarrier();
			_JockeysAreGettingReady = 0;
		} // End InitializeThreads() Method

		private void DetermineHandycapButton_Click(object sender, EventArgs e)
		{
			_TestingSpeed = true;

			InitializeThreads();

			Thread.MemoryBarrier();
			_JockeysAreGettingReady = 0;

			Thread.MemoryBarrier();
			_HorcesAreOff = (MaxHorses - 2) * MaxThreads;

			Thread.MemoryBarrier();
			_FirstTrott = (MaxHorses - 2) * MaxThreads;

			_LittleBlueEngineStartTime = DateTime.Now;
			_TheodoreTugboatStartTime = DateTime.Now;

			for (int i = 0; i < MaxThreads; ++i)
			{
				_LittleBlueEngineThread[i].Start();
				_TheodoreTugboatThread[i].Start();
			} // End for

			Thread.MemoryBarrier();
			_JockeysAreGettingReady = 1;

			while (_LittleBlueEngineFinished > 0 || _TheodoreTugboatFinished > 0)
			{
				Thread.MemoryBarrier();

#if (DEBUG)
					for (int i = 0; i < 50; ++i)
					{
						if (_LittleBlueEngineFinished > 0 || _TheodoreTugboatFinished > 0)
						{
							break;
						} // End if

						Thread.SpinWait(20);
					} // End for

					if (_LittleBlueEngineFinished > 0 || _TheodoreTugboatFinished > 0)
					{
						Thread.MemoryBarrier();

						Application.DoEvents();
						Thread.Sleep(500);
					}
#else
				Thread.Sleep(50);
#endif
			} // End while

			TimeSpan LittleBlueEngineTime = DateTime.Now.Subtract(_LittleBlueEngineStartTime);
			TimeSpan TheodoreTugboatTime = DateTime.Now.Subtract(_TheodoreTugboatStartTime);

			MessageBox.Show(this, "LittleBlueEngineTime: " + LittleBlueEngineTime + " TheodoreTugboatTime: " + TheodoreTugboatTime);


			Thread.MemoryBarrier();
			_JockeysAreGettingReady = 0;

			DetermineHandycapButton.Enabled = false;
			StartTheRaceButton.Enabled = false;

			Thread.MemoryBarrier();
			_HorcesAreOff = (MaxHorses - 2) * MaxThreads;

			Thread.MemoryBarrier();
			_FirstTrott = (MaxHorses - 2) * MaxThreads;

			_NitroStartTime = DateTime.Now;
			_LightningStartTime = DateTime.Now;

			for (int i = 0; i < MaxThreads; ++i)
			{
				_NitroThread[i].Start();
				_LightningThread[i].Start();
			} // End for

			Thread.MemoryBarrier();
			_JockeysAreGettingReady = 1;

			while (_NitroFinished > 0 || _LightningFinished > 0)
			{
				Thread.MemoryBarrier();

				#if (DEBUG)
					for (int i = 0; i < 50; ++i)
					{
						if (_NitroFinished > 0 || _LightningFinished > 0)
						{
							break;
						} // End if

						Thread.SpinWait(20);
					} // End for

					if (_NitroFinished > 0 || _LightningFinished > 0)
					{
						Thread.MemoryBarrier();

						Application.DoEvents();
						Thread.Sleep(500);
					}
				#else
					Thread.Sleep(50);
				#endif
			} // End while

			TimeSpan NitroTime = DateTime.Now.Subtract(_NitroStartTime);
			TimeSpan LightningTime = DateTime.Now.Subtract(_LightningStartTime);

			MessageBox.Show(this, "NitroTime: " + NitroTime + " LightningTime: " + LightningTime);


			Thread.MemoryBarrier();
			_JockeysAreGettingReady = 0;

			Thread.MemoryBarrier();
			_HorcesAreOff = (MaxHorses - 2) * MaxThreads;

			Thread.MemoryBarrier();
			_FirstTrott = (MaxHorses - 2) * MaxThreads;

			_EeyoreStartTime = DateTime.Now;
			_PinTheTailStartTime = DateTime.Now;

			for (int i = 0; i < MaxThreads; ++i)
			{
				_EeyoreThread[i].Start();
				_PinTheTailThread[i].Start();
			} // End for

			Thread.MemoryBarrier();
			_JockeysAreGettingReady = 1;

			while (_EeyoreFinished > 0 || _PinTheTailFinished > 0)
			{
				Thread.MemoryBarrier();

				#if (DEBUG)
					for (int i = 0; i < 50; ++i)
					{
						if (_EeyoreFinished > 0 || _PinTheTailFinished > 0)
						{
							break;
						} // End if

						Thread.SpinWait(20);
					} // End for

					if (_EeyoreFinished > 0 || _PinTheTailFinished > 0)
					{
						Thread.MemoryBarrier();

						Application.DoEvents();
						Thread.Sleep(500);
					}
				#else
					Thread.Sleep(50);
				#endif
			} // End while

			TimeSpan EeyoreTime = DateTime.Now.Subtract(_EeyoreStartTime);
			TimeSpan PinTheTailTime = DateTime.Now.Subtract(_PinTheTailStartTime);

			MessageBox.Show(this, "EeyoreTime: " + EeyoreTime + " PinTheTailTime: " + PinTheTailTime);


			long NitroTicks = NitroTime.Ticks;
			long EeyoreTicks = EeyoreTime.Ticks;
			long LittleBlueEngineTicks = LittleBlueEngineTime.Ticks;

			if (NitroTicks * 2 < EeyoreTicks + LittleBlueEngineTicks)
			{
				int AmountToAdd = (int)Math.Sqrt((int)NitroUpDown.Value) + 10;

				EeyoreUpDown.Value = (((long)(EeyoreUpDown.Value + AmountToAdd) * NitroTicks) / EeyoreTicks) % EeyoreUpDown.Maximum;
				PinTheTailUpDown.Value = (((long)(PinTheTailUpDown.Value + AmountToAdd) * NitroTicks) / EeyoreTicks) % PinTheTailUpDown.Maximum;

				LittleBlueEngineUpDown.Value = (((long)(LittleBlueEngineUpDown.Value  + AmountToAdd) * NitroTicks) / LittleBlueEngineTicks) % LittleBlueEngineUpDown.Maximum;
				TheodoreTugboatUpDown.Value = (((long)(TheodoreTugboatUpDown.Value  + AmountToAdd) * NitroTicks) / LittleBlueEngineTicks) % TheodoreTugboatUpDown.Maximum;

				NitroUpDown.Value = (NitroUpDown.Value + AmountToAdd) % NitroUpDown.Maximum;
				LightningUpDown.Value = (LightningUpDown.Value + AmountToAdd) % NitroUpDown.Maximum;
			} else if (EeyoreTicks * 2 < NitroTicks + LittleBlueEngineTicks) {
				int AmountToAdd = (int)Math.Sqrt((int)EeyoreUpDown.Value) + 10;

				NitroUpDown.Value = (((long)(NitroUpDown.Value + AmountToAdd) * EeyoreTicks) / NitroTicks) % NitroUpDown.Maximum;
				LightningUpDown.Value = (((long)(LightningUpDown.Value + AmountToAdd) * EeyoreTicks) / NitroTicks) % LightningUpDown.Maximum;

				LittleBlueEngineUpDown.Value = (((long)(LittleBlueEngineUpDown.Value) * EeyoreTicks + AmountToAdd) / LittleBlueEngineTicks) % LittleBlueEngineUpDown.Maximum;
				TheodoreTugboatUpDown.Value = (((long)(TheodoreTugboatUpDown.Value + AmountToAdd) * EeyoreTicks) / LittleBlueEngineTicks) % TheodoreTugboatUpDown.Maximum;

				EeyoreUpDown.Value = (EeyoreUpDown.Value + AmountToAdd) % EeyoreUpDown.Maximum;
				PinTheTailUpDown.Value = (PinTheTailUpDown.Value + AmountToAdd) % PinTheTailUpDown.Maximum;
			} else {
				int AmountToAdd = (int)Math.Sqrt((int)LittleBlueEngineUpDown.Value) + 10;

				NitroUpDown.Value = (((long)(NitroUpDown.Value + AmountToAdd) * LittleBlueEngineTicks) / NitroTicks) % NitroUpDown.Maximum;
				LightningUpDown.Value = (((long)(LightningUpDown.Value + AmountToAdd) * LittleBlueEngineTicks) / NitroTicks) % LightningUpDown.Maximum;

				EeyoreUpDown.Value = (((long)(EeyoreUpDown.Value + AmountToAdd) * LittleBlueEngineTicks) / EeyoreTicks) % EeyoreUpDown.Maximum;
				PinTheTailUpDown.Value = (((long)(PinTheTailUpDown.Value + AmountToAdd) * LittleBlueEngineTicks) / EeyoreTicks) % PinTheTailUpDown.Maximum;

				LittleBlueEngineUpDown.Value = (LittleBlueEngineUpDown.Value + AmountToAdd) % LittleBlueEngineUpDown.Maximum;
				TheodoreTugboatUpDown.Value = (TheodoreTugboatUpDown.Value + AmountToAdd) % TheodoreTugboatUpDown.Maximum;
			} // End if

			DetermineHandycapButton.Enabled = true;
			StartTheRaceButton.Enabled = true;
		} // End DetermineHandycapButton_Click() Method

		private void StartTheRaceButton_Click(object sender, EventArgs e)
		{
			_TestingSpeed = false;

			InitializeThreads();

			DetermineHandycapButton.Enabled = false;
			StartTheRaceButton.Enabled = false;

			for (int i = 0; i < MaxThreads; ++i)
			{
				_LittleBlueEngineThread[i].Start();
				_NitroThread[i].Start();
				_EeyoreThread[i].Start();
				_LightningThread[i].Start();
				_TheodoreTugboatThread[i].Start();
				_PinTheTailThread[i].Start();
			} // End for

			Thread.MemoryBarrier();
			_JockeysAreGettingReady = 1;

			while (_LittleBlueEngineFinished > 0 || _TheodoreTugboatFinished > 0 ||
						 _EeyoreFinished > 0 || _PinTheTailFinished > 0 ||
						 _NitroFinished < 0 || _LightningFinished > 0)
			{
				Thread.MemoryBarrier();
				Thread.Sleep(500);

				Application.DoEvents();
			} // End while

			DetermineHandycapButton.Enabled = true;
			StartTheRaceButton.Enabled = true;
		} // End DetermineHandycapButton_Click() Method

		private void NitroHorse()
		{
			Interlocked.Increment(ref _NitroFinished); 

			Thread.MemoryBarrier();
			while (_JockeysAreGettingReady == 0)
			{
				Thread.MemoryBarrier();
				Thread.Sleep(50);
			} // End while

			Interlocked.Increment(ref _HorcesAreOff);
			while (_HorcesAreOff < (MaxHorses * MaxThreads))
			{
				Thread.MemoryBarrier();
				Thread.Sleep(50);
			} // End while

			Gallop1(HorseType.Nitro, null);

			Interlocked.Increment(ref _FirstTrott);
			while (_FirstTrott < (MaxHorses * MaxThreads))
			{
				Thread.MemoryBarrier();
				Thread.Sleep(50);
			} // End while

			while (_NitroProgress < MaxProgress)
			{
				Gallop1(HorseType.Nitro, null);
				Gallop2(HorseType.Nitro, null);
				Stride(HorseType.Nitro, null);
			} // End while

			if (Interlocked.Decrement(ref _NitroFinished) == 1)
			{
				Interlocked.Decrement(ref _NitroFinished);
			}

			JoinThread(HorseType.Nitro);
		} // End NitroHorse() Method

		private void LightningHorse()
		{
			Interlocked.Increment(ref _LightningFinished); 

			Thread.MemoryBarrier();
			while (_JockeysAreGettingReady == 0)
			{
				Thread.MemoryBarrier();
				Thread.Sleep(50);
			} // End while

			Interlocked.Increment(ref _HorcesAreOff);
			while (_HorcesAreOff < (MaxHorses * MaxThreads))
			{
				Thread.MemoryBarrier();
				Thread.Sleep(50);
			} // End while

			Gallop1(HorseType.Lightning, null);

			Interlocked.Increment(ref _FirstTrott);
			while (_FirstTrott < (MaxHorses * MaxThreads))
			{
				Thread.MemoryBarrier();
				Thread.Sleep(50);
			} // End while

			while (_LightningProgress < MaxProgress)
			{
				Gallop1(HorseType.Lightning, null);
				Gallop2(HorseType.Lightning, null);
				Stride(HorseType.Lightning, null);
			} // End while

			if (Interlocked.Decrement(ref _LightningFinished) == 1)
			{
				Interlocked.Decrement(ref _LightningFinished);
			}

			JoinThread(HorseType.Lightning);
		} // End LightningHorse() Method

		private void EeyoreHorse()
		{
			Interlocked.Increment(ref _EeyoreFinished);

			Thread.MemoryBarrier();
			while (_JockeysAreGettingReady == 0)
			{
				Thread.MemoryBarrier();
				Thread.Sleep(50);
			} // End while

			Interlocked.Increment(ref _HorcesAreOff);
			while (_HorcesAreOff < (MaxHorses * MaxThreads))
			{
				Thread.MemoryBarrier();
				Thread.Sleep(50);
			} // End while

			Gallop1(HorseType.Eeyore, null);

			Interlocked.Increment(ref _FirstTrott);
			while (_FirstTrott < (MaxHorses * MaxThreads))
			{
				Thread.MemoryBarrier();
				Thread.Sleep(50);
			} // End while

			while (_EeyoreProgress < MaxProgress)
			{
				Gallop1(HorseType.Eeyore, null);
				Gallop2(HorseType.Eeyore, null);
				Stride(HorseType.Eeyore, null);
			} // End while

			if (Interlocked.Decrement(ref _EeyoreFinished) == 1)
			{
				Interlocked.Decrement(ref _EeyoreFinished);
			}

			JoinThread(HorseType.Eeyore);
		} // End EeyoreHorse() Method

		private void PinTheTailHorse()
		{
			Interlocked.Increment(ref _PinTheTailFinished);

			Thread.MemoryBarrier();
			while (_JockeysAreGettingReady == 0)
			{
				Thread.MemoryBarrier();
				Thread.Sleep(50);
			} // End while

			Interlocked.Increment(ref _HorcesAreOff);
			while (_HorcesAreOff < (MaxHorses * MaxThreads))
			{
				Thread.MemoryBarrier();
				Thread.Sleep(50);
			} // End while

			Gallop1(HorseType.PinTheTail, null);

			Interlocked.Increment(ref _FirstTrott);
			while (_FirstTrott < (MaxHorses * MaxThreads))
			{
				Thread.MemoryBarrier();
				Thread.Sleep(50);
			} // End while

			while (_PinTheTailProgress < MaxProgress)
			{
				Gallop1(HorseType.PinTheTail, null);
				Gallop2(HorseType.PinTheTail, null);
				Stride(HorseType.PinTheTail, null);
			} // End while

			if (Interlocked.Decrement(ref _PinTheTailFinished) == 1)
			{
				Interlocked.Decrement(ref _PinTheTailFinished);
			}

			JoinThread(HorseType.PinTheTail);
		} // End PinTheTailHorse() Method

		private void LittleBlueEngineHorse()
		{
			Interlocked.Increment(ref _LittleBlueEngineFinished);

			Thread.MemoryBarrier();
			while (_JockeysAreGettingReady == 0)
			{
				Thread.MemoryBarrier();
				Thread.Sleep(50);
			} // End while

			Interlocked.Increment(ref _HorcesAreOff);
			while (_HorcesAreOff < (MaxHorses * MaxThreads))
			{
				Thread.MemoryBarrier();
				Thread.Sleep(50);
			} // End while

			Gallop1(HorseType.LittleBlueEngine, null);

			Interlocked.Increment(ref _FirstTrott);
			while (_FirstTrott < (MaxHorses * MaxThreads))
			{
				Thread.MemoryBarrier();
				Thread.Sleep(50);
			} // End while

			while (_LittleBlueEngineProgress < MaxProgress)
			{
				Gallop1(HorseType.LittleBlueEngine, null);
				Gallop2(HorseType.LittleBlueEngine, null);
				Stride(HorseType.LittleBlueEngine, null);
			} // End while

			if (Interlocked.Decrement(ref _LittleBlueEngineFinished) == 1)
			{
				Interlocked.Decrement(ref _LittleBlueEngineFinished);
			}
			
			JoinThread(HorseType.LittleBlueEngine);
		} // End LittleBlueEngineHorse() Method

		private void TheodoreTugboatHorse()
		{
			Interlocked.Increment(ref _TheodoreTugboatFinished);

			Thread.MemoryBarrier();
			while (_JockeysAreGettingReady == 0)
			{
				Thread.MemoryBarrier();
				Thread.Sleep(50);
			} // End while

			Interlocked.Increment(ref _HorcesAreOff);
			while (_HorcesAreOff < (MaxHorses * MaxThreads))
			{
				Thread.MemoryBarrier();
				Thread.Sleep(50);
			} // End while

			Gallop1(HorseType.TheodoreTugboat, null);

			Interlocked.Increment(ref _FirstTrott);
			while (_FirstTrott < (MaxHorses * MaxThreads))
			{
				Thread.MemoryBarrier();
				Thread.Sleep(50);
			} // End while

			while (_TheodoreTugboatProgress < MaxProgress)
			{
				Gallop1(HorseType.TheodoreTugboat, null);
				Gallop2(HorseType.TheodoreTugboat, null);
				Stride(HorseType.TheodoreTugboat, null);
			} // End while

			if (Interlocked.Decrement(ref _TheodoreTugboatFinished) == 1)
			{
				Interlocked.Decrement(ref _TheodoreTugboatFinished);
			}

			JoinThread(HorseType.TheodoreTugboat);
		} // End TheodoreTugboatHorse() Method

		private void Gallop1(HorseType type, object algorithmTag)
		{
			IAsyncResult cookie = BeginGallop1(type);

			int fullCount = 0;

			for (int i = 0; i <  Math.Sqrt(GetWorkLoad(type)); ++i)
			{
				try
				{
					BeginWriteLock(type);
					fullCount += 1;
				}
				finally
				{
					EndWriteLock(type);
				} // End try
			} // End for

			EndGallop1(type, cookie);
		} // End Gallop1 Method

		private void Gallop2(HorseType type, object algorithmTag)
		{
			IAsyncResult cookie = BeginGallop2(type);

			int fullCount = 0;

			for (int i = 0; i < Math.Sqrt(GetWorkLoad(type)); ++i)
			{
				try
				{
					BeginWriteLock(type);
					fullCount += 1;
				}
				finally
				{
					EndWriteLock(type);
				} // End try
			} // End for

			EndGallop2(type, cookie);
		} // End Gallop1 Method

		private void Stride(HorseType type, object algorithmTag)
		{
			int fullCount = 0;

			for (int i = 0; i < GetWorkLoad(type); ++i)
			{
				try
				{
					BeginWriteLock(type);
					fullCount += 1;
				}
				finally
				{
					EndWriteLock(type);
				} // End try
			} // End for

			switch (type)
			{
				case HorseType.Nitro:
					{
						if (_NitroProgress < MaxProgress)
						{
							Interlocked.Increment(ref _NitroProgress);

							if (GetProgress(type) != _NitroProgress / (MaxProgress / 100))
							{
								SetProgress(type, _NitroProgress / (MaxProgress / 100));
							} // End if
						} // End If
					} break;
				case HorseType.Lightning:
					{
						if (_LightningProgress < MaxProgress)
						{
							Interlocked.Increment(ref _LightningProgress);

							if (GetProgress(type) != _LightningProgress / (MaxProgress / 100))
							{
								SetProgress(type, _LightningProgress / (MaxProgress / 100));
							} // End if
						} // End If
					} break;
				case HorseType.Eeyore:
					{
						if (_EeyoreProgress < MaxProgress)
						{
							Interlocked.Increment(ref _EeyoreProgress);

							if (GetProgress(type) != _EeyoreProgress / (MaxProgress / 100))
							{
								SetProgress(type, _EeyoreProgress / (MaxProgress / 100));
							} // End if
						} // End if
					} break;
				case HorseType.PinTheTail:
					{
						if (_PinTheTailProgress < MaxProgress)
						{
							Interlocked.Increment(ref _PinTheTailProgress);

							if (GetProgress(type) != _PinTheTailProgress / (MaxProgress / 100))
							{
								SetProgress(type, _PinTheTailProgress / (MaxProgress / 100));
							} // End if
						} // End if
					} break;
				case HorseType.LittleBlueEngine:
					{
						if (_LittleBlueEngineProgress < MaxProgress)
						{
							Interlocked.Increment(ref _LittleBlueEngineProgress);

							if (GetProgress(type) != _LittleBlueEngineProgress / (MaxProgress / 100))
							{
								SetProgress(type, _LittleBlueEngineProgress / (MaxProgress / 100));
							} // End if
						} // End if
					} break;
				case HorseType.TheodoreTugboat:
					{
						if (_TheodoreTugboatProgress < MaxProgress)
						{
							Interlocked.Increment(ref _TheodoreTugboatProgress);

							if (GetProgress(type) != _TheodoreTugboatProgress / (MaxProgress / 100))
							{
								SetProgress(type, _TheodoreTugboatProgress / (MaxProgress / 100));
							} // End if
						} // End if
					} break;
			} // End switch
		} // End Gallop1 Method

		#region Threading Functions
			private int JoinThread(HorseType type)
			{
				if (_TestingSpeed)
				{
					return 1;
				} // End if

				if (InvokeRequired)
				{
					BeginInvoke(new GetMethod(JoinThread), type);
				}
				else
				{
					switch (type)
					{
						case HorseType.Nitro:
							{
								for (int i = 0; i < MaxThreads; ++i)
								{
									//_NitroThread[i].Join();
								} // End for
							} break;
						case HorseType.Lightning:
							{
								for (int i = 0; i < MaxThreads; ++i)
								{
									//_LightningThread[i].Join();
								} // End for
							} break;
						case HorseType.Eeyore:
							{
								for (int i = 0; i < MaxThreads; ++i)
								{
									//_EeyoreThread[i].Join();
								} // End for
							} break;
						case HorseType.PinTheTail:
							{
								for (int i = 0; i < MaxThreads; ++i)
								{
									//_PinTheTailThread[i].Join();
								} // End for
							} break;
						case HorseType.LittleBlueEngine:
							{
								for (int i = 0; i < MaxThreads; ++i)
								{
									//_LittleBlueEngineThread[i].Join();
								} // End for
							} break;
						case HorseType.TheodoreTugboat:
							{
								for (int i = 0; i < MaxThreads; ++i)
								{
									//_TheodoreTugboatThread[i].Join();
								} // End for
							} break;
					} // End switch
				} // End if

				return 0;
			} // End JoinThread() Method

			private int GetWorkLoad(HorseType type)
			{
				try 
				{	        
					BeginReadLock(type);

					switch (type)
					{
						case HorseType.Nitro:
							{
								return Decimal.ToInt32(NitroUpDown.Value);
							} // break;
						case HorseType.Lightning:
							{
								return Decimal.ToInt32(LightningUpDown.Value);
							} // break;
						case HorseType.Eeyore:
							{
								return Decimal.ToInt32(EeyoreUpDown.Value);
							} // break;
						case HorseType.PinTheTail:
							{
								return Decimal.ToInt32(PinTheTailUpDown.Value);
							} // break;
						case HorseType.LittleBlueEngine:
							{
								return Decimal.ToInt32(LittleBlueEngineUpDown.Value);
							} // break;
						case HorseType.TheodoreTugboat:
							{
								return Decimal.ToInt32(TheodoreTugboatUpDown.Value);
							} // break;
					} // End switch
				}
				finally
				{
					EndReadLock(type);				
				} // End try

				return 0;
			} // End GetWorkLoad() Method

			private void SetWorkLoad(HorseType type, int value)
			{
				if (_TestingSpeed)
				{
					return;
				} // End if

				if (InvokeRequired)
				{
					try
					{
						BeginWriteLock(type);

						BeginInvoke(new SetMethod(SetWorkLoad), type, value);
					}
					finally
					{
						EndWriteLock(type);				
					} // End try
				} else {
					switch (type)
					{
						case HorseType.Nitro:
							{
								NitroUpDown.Value = value;
							} break;
						case HorseType.Lightning:
							{
								LightningUpDown.Value = value;
							} break;
						case HorseType.Eeyore:
							{
								EeyoreUpDown.Value = value;
							} break;
						case HorseType.PinTheTail:
							{
								PinTheTailUpDown.Value = value;
							} break;
						case HorseType.LittleBlueEngine:
							{
								LittleBlueEngineUpDown.Value = value;
							} break;
						case HorseType.TheodoreTugboat:
							{
								TheodoreTugboatUpDown.Value = value;
							} break;
					} // End switch
				} // End if
			} // End SetWorkLoad() Method

			private int GetProgress(HorseType type)
			{
				try
				{
					BeginReadLock(type);

					switch (type)
					{
						case HorseType.Nitro:
							{
								return NitroProgressBar.Value;
							} // break;
						case HorseType.Lightning:
							{
								return LightningProgressBar.Value;
							} // break;
						case HorseType.Eeyore:
							{
								return EeyoreProgressBar.Value;
							} // break;
						case HorseType.PinTheTail:
							{
								return PinTheTailProgressBar.Value;
							} // break;
						case HorseType.LittleBlueEngine:
							{
								return LittleBlueEngineProgressBar.Value;
							} // break;
						case HorseType.TheodoreTugboat:
							{
								return TheodoreTugboatProgressBar.Value;
							} // break;
					} // End switch
				}
				finally
				{
					EndReadLock(type);
				} // End try

				return 0;
			} // End GetWorkLoad() Method

			private void SetProgress(HorseType type, int value)
			{
				if (_TestingSpeed)
				{
					return;
				} // End if

				if (InvokeRequired)
				{
					try
					{
						BeginWriteLock(type);

						BeginInvoke(new SetMethod(SetProgress), type, value);
					}
					finally
					{
						EndWriteLock(type);
					} // End try
				}
				else
				{
					switch (type)
					{
						case HorseType.Nitro:
							{
								NitroProgressBar.Value = value;
							} break;
						case HorseType.Lightning:
							{
								LightningProgressBar.Value = value;
							} break;
						case HorseType.Eeyore:
							{
								EeyoreProgressBar.Value = value;
							} break;
						case HorseType.PinTheTail:
							{
								PinTheTailProgressBar.Value = value;
							} break;
						case HorseType.LittleBlueEngine:
							{
								LittleBlueEngineProgressBar.Value = value;
							} break;
						case HorseType.TheodoreTugboat:
							{
								TheodoreTugboatProgressBar.Value = value;
							} break;
					} // End switch
				} // End if
			} // End SetWorkLoad() Method

			private IAsyncResult BeginGallop1(HorseType type)
			{
				return null;
				//return BeginInvoke(new PressGallopButtonMethod(PressGallop1Button), type, true);
			} // End BeginGallop1() Method

			private void EndGallop1(HorseType type, IAsyncResult waitResult)
			{
				// If need be, waits for the gui to finish pressing the button before releasing it.
				//EndInvoke(waitResult);

				//BeginInvoke(new PressGallopButtonMethod(PressGallop1Button), type, false);
			} // End BeginGallop1() Method

			private IAsyncResult BeginGallop2(HorseType type)
			{
				return null;
				//return BeginInvoke(new PressGallopButtonMethod(PressGallop2Button), type, true);
			} // End BeginGallop2() Method

			private void EndGallop2(HorseType type, IAsyncResult waitResult)
			{
				// If need be, waits for the gui to finish pressing the button before releasing it.
				//EndInvoke(waitResult);

				//BeginInvoke(new PressGallopButtonMethod(PressGallop2Button), type, false);
			} // End BeginGallop2() Method

			private void BeginReadLock(HorseType type)
			{
				switch (type)
				{
					case HorseType.Nitro:
						{
							_NitroLock.EnterReadLock();
						} break;
					case HorseType.Lightning:
						{
							_LightningLock.EnterReadLock();
						} break;
					case HorseType.Eeyore:
						{
							_EeyoreLock.AcquireReaderLock(-1);
						} break;
					case HorseType.PinTheTail:
						{
							_PinTheTailLock.AcquireReaderLock(-1);
						} break;
					case HorseType.LittleBlueEngine:
						{
							_LittleBlueEngineLock.LockForReading();
						} break;
					case HorseType.TheodoreTugboat:
						{
							_TheodoreTugboatLock.LockForReading();
						} break;
				} // End switch
			} // End PressGallop1Button Method

			private void EndReadLock(HorseType type)
			{
				switch (type)
				{
					case HorseType.Nitro:
						{
							_NitroLock.ExitReadLock();
						} break;
					case HorseType.Lightning:
						{
							_LightningLock.ExitReadLock();
						} break;
					case HorseType.Eeyore:
						{
							_EeyoreLock.ReleaseReaderLock();
						} break;
					case HorseType.PinTheTail:
						{
							_PinTheTailLock.ReleaseReaderLock();
						} break;
					case HorseType.LittleBlueEngine:
						{
							_LittleBlueEngineLock.UnlockForReading();
						} break;
					case HorseType.TheodoreTugboat:
						{
							_TheodoreTugboatLock.UnlockForReading();
						} break;
				} // End switch
			} // End PressGallop2Button Method

			private void BeginWriteLock(HorseType type)
			{
				switch (type)
				{
					case HorseType.Nitro:
						{
							_NitroLock.EnterWriteLock();
						} break;
					case HorseType.Lightning:
						{
							_LightningLock.EnterWriteLock();
						} break;
					case HorseType.Eeyore:
						{
							_EeyoreLock.AcquireWriterLock(-1);
						} break;
					case HorseType.PinTheTail:
						{
							_PinTheTailLock.AcquireWriterLock(-1);
						} break;
					case HorseType.LittleBlueEngine:
						{
							_LittleBlueEngineLock.LockForWriting();
						} break;
					case HorseType.TheodoreTugboat:
						{
							_TheodoreTugboatLock.LockForWriting();
						} break;
				} // End switch
			} // End PressGallop1Button Method

			private void EndWriteLock(HorseType type)
			{
				switch (type)
				{
					case HorseType.Nitro:
						{
							_NitroLock.ExitWriteLock();
						} break;
					case HorseType.Lightning:
						{
							_LightningLock.ExitWriteLock();
						} break;
					case HorseType.Eeyore:
						{
							_EeyoreLock.ReleaseWriterLock();
						} break;
					case HorseType.PinTheTail:
						{
							_PinTheTailLock.ReleaseWriterLock();
						} break;
					case HorseType.LittleBlueEngine:
						{
							_LittleBlueEngineLock.UnlockForWriting();
						} break;
					case HorseType.TheodoreTugboat:
						{
							_TheodoreTugboatLock.UnlockForWriting();
						} break;
				} // End switch
			} // End PressGallop2Button Method
		#endregion

		#region UI Functions
			private void PressGallop1Button(HorseType type, bool pressed)
			{
				switch (type)
				{
					case HorseType.Nitro:
						{
							NitroGallop1CheckBox.Checked = pressed;
						} break;
					case HorseType.Lightning:
						{
							LightningGallop1CheckBox.Checked = pressed;
						} break;
					case HorseType.Eeyore:
						{
							this.EeyoreGallop1CheckBox.Checked = pressed;
						} break;
					case HorseType.PinTheTail:
						{
							PinTheTailGallop1CheckBox.Checked = pressed;
						} break;
					case HorseType.LittleBlueEngine:
						{
							LittleBlueEngineGallop1CheckBox.Checked = pressed;
						} break;
					case HorseType.TheodoreTugboat:
						{
							TheodoreTugboatGallop1CheckBox.Checked = pressed;
						} break;
				} // End switch
			} // End PressGallop1Button Method

			private void PressGallop2Button(HorseType type, bool pressed)
			{
				switch (type)
				{
					case HorseType.Nitro:
						{
							NitroGallop2CheckBox.Checked = pressed;
						} break;
					case HorseType.Lightning:
						{
							LightningGallop2CheckBox.Checked = pressed;
						} break;
					case HorseType.Eeyore:
						{
							this.EeyoreGallop2CheckBox.Checked = pressed;
						} break;
					case HorseType.PinTheTail:
						{
							PinTheTailGallop2CheckBox.Checked = pressed;
						} break;
					case HorseType.LittleBlueEngine:
						{
							LittleBlueEngineGallop2CheckBox.Checked = pressed;
						} break;
					case HorseType.TheodoreTugboat:
						{
							TheodoreTugboatGallop2CheckBox.Checked = pressed;
						} break;
				} // End switch
			}
		#endregion
	} // End Form1 Class
} // End PerformanceGraph Class
